Skip to main content

Action Metadata


The metadata of your action is what will be translated into the visual information of the blink once it is rendered on a client. This metadata consists of the following data in JSON format.

  • Icon: The image of your blink.
  • Title: The title of your blink.
  • Description: Description of your blink.
  • Label: Main label of your blink.
  • links: Set of links that make up your blink.
    • actions: Set of buttons that trigger the actions of your blink; there can be one or more.
      • label: Text of your button.
      • href: URL to which your input will request a transaction in your Solana Action.
      • parameters: Set of inputs that will allow you to capture information from users in your blink; there can be one or more.
        • label: Text of your input.
        • name: Identifier for your input.
        • required: Indicates whether it is a mandatory input to complete in order to request the transaction.
  • disabled: Value indicating whether your blink is disabled or active.
  • error: Error message in case there is an issue during the request process to your Solana Action.

blink-ref-1_Mesa de trabajo 1.png

NOTE: The yellow message appears on all blinks that are not verified by dialect.io. To remove it and allow your blink to appear on platform X, simply fill out the Dialect form and wait for approval.


This metadata is configurable from Znap using the action macro. To generate the appearance of the previous blink in Znap, the following snippet of code should be used outside of our collection module:

use znap::prelude::*;

#[collection]
pub mod kmno_staking {}

#[derive(Action)]
#[action(
icon = "https://raw.githubusercontent.com/leandrogavidia/files/main/kmno-staking.png",
title = "Stake KMNO",
description = "Stake your KMNO to boost points, vote on proposals, and earn rewards in Kamino Finance",
label = "Stake",
link = {
label = "Stake",
href = "/api/staking?amount={amount}&method=stake",
parameter = { label = "Amount", name = "amount" }
},
link = {
label = "Unstake",
href = "/api/staking?amount={amount}&method=unstake",
parameter = { label = "Amount", name = "amount" }
},
)]
#[query(amount: f32, method: String)]
pub struct StakingAction;

Parameters

In the previous example, you can see that the parameters are an object with two keys: label and name. The label is the text that appears on the blink for users to see, while the name is how we identify the parameter in our code when we receive a request to our Solana Action.

There are two types of parameters: static and dynamic. Regardless of their type, it is necessary to use the query macro, where you must specify the name of the parameter and the type you expect to receive. This will allow you to reject requests if either of the two parameters does not meet the expected type.

Static

In the previous example, you can see that static parameters are those that have a fixed value, such as: method=stake and method=unstake. You will always receive one of these two values depending on the action taken by the user in the blink.

Dynamic

On the other hand, dynamic parameters are those represented as inputs for the user, and the value you will receive will depend on the user's input; you do not know exactly what you will receive. To establish this in your action, you should place the name of the parameter and, as the value, the name of the parameter in your action, which in this case has the same name: amount={amount}.

Parameters Capture

Capturing the values of the parameters we configured earlier is quite simple. Here’s a brief example of how you can access them within a function of your action:

pub fn stake(ctx: Context<StakingAction>) -> Result<ActionTransaction> {
let method = ctx.query.method.clone();
let amount = ctx.query.amount;
}

Once captured, you can utilize their values or create additional validations to ensure that you received what you expected.

Advanced

Dynamic Action Metadata

Imagine that now you want not only the parameters but also the title, description, actions, or any information of your blink to be dynamic, and even have this dynamic information created through API requests or other methods or validations prior to rendering your blink.

We achieve this by creating and using a function that returns the Action Metadata of our action. We will replicate the metadata of our action but using this function, which should be placed within our collection module, as follows:

use znap::prelude::*;

#[collection]
pub mod kmno_staking {
pub fn stake(ctx: Context<StakingAction>) -> Result<ActionTransaction> {
let method = ctx.query.method.clone();
let amount = ctx.query.amount;
}

fn get_stake(ctx: Context<StakingAction>) -> Result<ActionMetadata> {
let amount: &str = "{amount}";

let links = ActionLinks {
actions: vec![
LinkedAction {
label: "Stake".to_string(),
href: format!("/api/staking?amount={}&method=stake", amount),
parameters: vec![LinkedActionParameter {
label: "Amount".to_string(),
name: "amount".to_string(),
required: true,
}],
},
LinkedAction {
label: "Unstake".to_string(),
href: format!("/api/staking?amount={}&method=unstake", amount),
parameters: vec![LinkedActionParameter {
label: "Amount".to_string(),
name: "amount".to_string(),
required: true,
}],
},
],
};

Ok(ActionMetadata {
title: "Stake KMNO".to_string(),
description: "Stake your KMNO to boost points, vote on proposals, and earn rewards in Kamino Finance".to_string(),
icon: "https://raw.githubusercontent.com/leandrogavidia/files/main/kmno-staking.png".to_string(),
label: "Stake".to_string(),
disabled: false,
error: None,
links: Some(links),
})
}
}

#[derive(Action)]
#[query(amount: f32, method: String)]
pub struct StakingAction;

This way, within the get_stake function, you will be able to perform different flows or operations to display one piece of information or another depending on the cases! Practice with the example.